module ShiftMultiplier #(
    parameter WIDTH = 64,
    parameter E = WIDTH + 2,
    parameter W = E * 2
) (
    input   logic               clock,
    input   logic               reset,
    input   logic [WIDTH-1:0]   x,
    input   logic [WIDTH-1:0]   y,
    input   logic [1:0]         signs,
    input   logic               valid,
    output  logic               ready,
    output  logic [2*WIDTH-1:0] result,
    output  logic               done
);

    assign ready = (state == IDLE);
    assign done  = (state == DONE);
    assign result = R[2*WIDTH-1:0];

    // Partial Product
    Radix4BoothProduct #(
        .WIDTH(W)
    ) booth (
        .y      (Y[2:0]),
        .x      (X[W-1:0]),
        .p      (P),
        .c      (C)
    );

    // Adder
    wire [W-1:0]    adder_x     = R;
    wire [W-1:0]    adder_y     = P;
    wire            adder_cin   = C;
    logic [W-1:0]   adder_sum;
    /* verilator lint_off UNUSEDSIGNAL */
    logic           adder_cout;
    /* verilator lint_off WIDTH */
    assign {adder_cout, adder_sum} = adder_x + adder_y + adder_cin;

    // State Machine
    logic [E:0]     Y;
    logic [W-1:0]   X;
    logic [W-1:0]   R;
    logic [W-1:0]   P;
    logic           C;

    localparam IDLE = 3'b001, CALC = 3'b010, DONE = 3'b100;
    logic [2:0] state;
    logic       y_sign;

    always_ff @(posedge clock) begin
        if (reset) begin
            state   <= IDLE;
            y_sign  <= 0;
            X   <= 0;
            Y   <= 0;
            R   <= 0;
        end
        else begin
            case (state) 
                IDLE: begin
                    if (valid & ready) begin
                        state   <= CALC;
                        y_sign  <= signs[0] & y[WIDTH-1];
                        X   <= { {(WIDTH+4){signs[1] & x[WIDTH-1]}}, x}; // signs[1] ? x[WIDTH-1] : 1'b0
                        Y   <= { { 2{signs[0] & y[WIDTH-1]}}, y, 1'b0 }; // signs[0] ? y[WIDTH-1] : 1'b0
                        R   <= 0;
                    end
                    else begin
                        state   <= IDLE;
                    end
                end
                CALC: begin
                    // 继续计算
                    /// ~y_sign ? ((|Y[E-1:1]) | Y[0]) : (|Y[E-1:1] | 1'b0)
                    if ((|Y[E-1:1]) | (~y_sign & Y[0])) begin
                        state   <= CALC;
                        X   <= { X[W-1:0], 2'b00 }; // X   <= X << 2;
                        Y   <= { 2'b00, Y[E:2] };   // Y   <= Y >> 2;
                        R   <= adder_sum;
                    end
                    // 结束计算
                    else begin
                        state   <= DONE;
                    end
                end
                DONE: begin
                    state   <= IDLE;
                end
                default: begin
                    state   <= IDLE;
                end
            endcase
        end
    end
    
endmodule //Multiplier
